// ============================================== //
// instr decode macros， 65 instructions in total //
// ============================================== //
`define OP_BEQ    0
`define OP_BNE    1
`define OP_BLTZ   2
`define OP_BGEZ   3
`define OP_BLTZAL 4
`define OP_BGEZAL 5
`define OP_BLEZ   6
`define OP_BGTZ   7
`define OP_J      8
`define OP_JAL    9
`define OP_JR    10
`define OP_JALR  11
`define NR_BR_OP 12

`define OP_LB    0
`define OP_LH    1
`define OP_LWL   2
`define OP_LW    3
`define OP_LBU   4
`define OP_LHU   5
`define OP_LWR   6
`define NR_LD_OP 7

`define OP_SB    0
`define OP_SH    1
`define OP_SWL   2
`define OP_SW    3
`define OP_SWR   4
`define NR_ST_OP 5

`define INSTR_SLL   wire instr_sll   = (opcode == 6'b000000) && (funct == 6'b000000)
`define INSTR_SRL   wire instr_srl   = (opcode == 6'b000000) && (funct == 6'b000010)
`define INSTR_SRA   wire instr_sra   = (opcode == 6'b000000) && (funct == 6'b000011)
`define INSTR_SLLV  wire instr_sllv  = (opcode == 6'b000000) && (funct == 6'b000100)
`define INSTR_SRLV  wire instr_srlv  = (opcode == 6'b000000) && (funct == 6'b000110)
`define INSTR_SRAV  wire instr_srav  = (opcode == 6'b000000) && (funct == 6'b000111)
`define INSTR_JR    wire instr_jr    = (opcode == 6'b000000) && (funct == 6'b001000)
`define INSTR_JALR  wire instr_jalr  = (opcode == 6'b000000) && (funct == 6'b001001)

`define INSTR_SYSCALL wire instr_syscall = (opcode == 6'b000000) && (funct == 6'b001100)
`define INSTR_BREAK   wire instr_break   = (opcode == 6'b000000) && (funct == 6'b001101)

`define INSTR_MFHI  wire instr_mfhi  = (opcode == 6'b000000) && (funct == 6'b010000)
`define INSTR_MTHI  wire instr_mthi  = (opcode == 6'b000000) && (funct == 6'b010001)
`define INSTR_MFLO  wire instr_mflo  = (opcode == 6'b000000) && (funct == 6'b010010)
`define INSTR_MTLO  wire instr_mtlo  = (opcode == 6'b000000) && (funct == 6'b010011)

`define INSTR_MULT  wire instr_mult  = (opcode == 6'b000000) && (funct == 6'b011000)
`define INSTR_MULTU wire instr_multu = (opcode == 6'b000000) && (funct == 6'b011001)
`define INSTR_DIV   wire instr_div   = (opcode == 6'b000000) && (funct == 6'b011010)
`define INSTR_DIVU  wire instr_divu  = (opcode == 6'b000000) && (funct == 6'b011011)

`define INSTR_ADD   wire instr_add   = (opcode == 6'b000000) && (funct == 6'b100000)
`define INSTR_ADDU  wire instr_addu  = (opcode == 6'b000000) && (funct == 6'b100001)
`define INSTR_SUB   wire instr_sub   = (opcode == 6'b000000) && (funct == 6'b100010)
`define INSTR_SUBU  wire instr_subu  = (opcode == 6'b000000) && (funct == 6'b100011)

`define INSTR_AND   wire instr_and   = (opcode == 6'b000000) && (funct == 6'b100100)
`define INSTR_OR    wire instr_or    = (opcode == 6'b000000) && (funct == 6'b100101)
`define INSTR_XOR   wire instr_xor   = (opcode == 6'b000000) && (funct == 6'b100110)
`define INSTR_NOR   wire instr_nor   = (opcode == 6'b000000) && (funct == 6'b100111)
`define INSTR_SLT   wire instr_slt   = (opcode == 6'b000000) && (funct == 6'b101010)
`define INSTR_SLTU  wire instr_sltu  = (opcode == 6'b000000) && (funct == 6'b101011)

`define INSTR_BLTZ   wire instr_bltz   = (opcode == 6'b000001) && (rt == 5'b00000)
`define INSTR_BGEZ   wire instr_bgez   = (opcode == 6'b000001) && (rt == 5'b00001)
`define INSTR_BLTZAL wire instr_bltzal = (opcode == 6'b000001) && (rt == 5'b10000)
`define INSTR_BGEZAL wire instr_bgezal = (opcode == 6'b000001) && (rt == 5'b10001)

`define INSTR_J     wire instr_j     = (opcode == 6'b000010)
`define INSTR_JAL   wire instr_jal   = (opcode == 6'b000011)

`define INSTR_BEQ   wire instr_beq   = (opcode == 6'b000100)
`define INSTR_BNE   wire instr_bne   = (opcode == 6'b000101)
`define INSTR_BLEZ  wire instr_blez  = (opcode == 6'b000110)
`define INSTR_BGTZ  wire instr_bgtz  = (opcode == 6'b000111)

`define INSTR_ADDI  wire instr_addi  = (opcode == 6'b001000)
`define INSTR_ADDIU wire instr_addiu = (opcode == 6'b001001)
`define INSTR_SLTI  wire instr_slti  = (opcode == 6'b001010)
`define INSTR_SLTIU wire instr_sltiu = (opcode == 6'b001011)
`define INSTR_ANDI  wire instr_andi  = (opcode == 6'b001100)
`define INSTR_ORI   wire instr_ori   = (opcode == 6'b001101)
`define INSTR_XORI  wire instr_xori  = (opcode == 6'b001110)
`define INSTR_LUI   wire instr_lui   = (opcode == 6'b001111)

`define INSTR_ERET  wire instr_eret  = (opcode == 6'b010000) && (rs == 5'b10000) && (funct == 6'b011000)
`define INSTR_MFC0  wire instr_mfc0  = (opcode == 6'b010000) && (rs == 5'b00000)
`define INSTR_MTC0  wire instr_mtc0  = (opcode == 6'b010000) && (rs == 5'b00100)
`define INSTR_TLBP  wire instr_tlbp  = (opcode == 6'b010000) && (rs == 5'b10000) && (funct == 6'b001000)
`define INSTR_TLBR  wire instr_tlbr  = (opcode == 6'b010000) && (rs == 5'b10000) && (funct == 6'b000001)
`define INSTR_TLBWI wire instr_tlbwi = (opcode == 6'b010000) && (rs == 5'b10000) && (funct == 6'b000010)
`define INSTR_TLBWR wire instr_tlbwr = (opcode == 6'b010000) && (rs == 5'b10000) && (funct == 6'b000110)

`define INSTR_MUL wire instr_mul  = (opcode == 6'b011100) && (funct == 6'b000010)

`define INSTR_LB    wire instr_lb    = (opcode == 6'b100000)
`define INSTR_LH    wire instr_lh    = (opcode == 6'b100001)
`define INSTR_LWL   wire instr_lwl   = (opcode == 6'b100010)
`define INSTR_LW    wire instr_lw    = (opcode == 6'b100011)
`define INSTR_LBU   wire instr_lbu   = (opcode == 6'b100100)
`define INSTR_LHU   wire instr_lhu   = (opcode == 6'b100101)
`define INSTR_LWR   wire instr_lwr   = (opcode == 6'b100110)

`define INSTR_SB    wire instr_sb    = (opcode == 6'b101000)
`define INSTR_SH    wire instr_sh    = (opcode == 6'b101001)
`define INSTR_SWL   wire instr_swl   = (opcode == 6'b101010)
`define INSTR_SW    wire instr_sw    = (opcode == 6'b101011)
`define INSTR_SWR   wire instr_swr   = (opcode == 6'b101110)

`define INSTR_MATCH wire instr_match = (opcode == 6'b011100) && (sa == 5'b11100) && (funct == 6'b110111)

// =================== //
// instr format macros //
// =================== //
`define INSTR_OPCODE 31:26
`define INSTR_RS     25:21
`define INSTR_RT     20:16
`define INSTR_RD     15:11
`define INSTR_SA     10: 6
`define INSTR_FUNCT   5: 0
`define INSTR_INDEX  25: 0
`define INSTR_IMM    15: 0
`define INSTR_SEL     2: 0

// ========================= //
// alu operation code macros //
// ========================= //
`define OP_ADD  0
`define OP_SUB  1
`define OP_AND  2
`define OP_NOR  3
`define OP_OR   4
`define OP_XOR  5
`define OP_SLT  6
`define OP_SLTU 7
`define OP_SLL  8
`define OP_SRA  9
`define OP_SRL 10
`define OP_LUI 11

// ============ //
// hi lo macros //
// ============ //
`define HI 1
`define LO 0

// ================ //
// exception macros //
// ================ //
`define EX_INT  5'h00
`define EX_TLBM 5'h01
`define EX_TLBL 5'h02
`define EX_TLBS 5'h03
`define EX_ADEL 5'h04
`define EX_ADES 5'h05
`define EX_SYS  5'h08
`define EX_BP   5'h09
`define EX_RI   5'h0a
`define EX_OV   5'h0c

// ================= //
// pc related macros //
// ================= //
`define START_POINT 32'hbfc00000
`define EX_PC       32'hbfc00380
`define TLBRE_PC    32'hbfc00200

// ================= //
// tlb config macros //
// ================= //
`define TLB_NUM 16

// ======================== //
// simulation config macros //
// ======================== //
// `define RUN_SIM